home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TPUG - Toronto PET Users Group
/
TPUG Users Group CD
/
TPUG Users Group CD.iso
/
AMIGA
/
(A)TB
/
(A)TBL.ADF
/
Utility
/
lp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-03-23
|
8KB
|
257 lines
/*************************************************
* Name : lightpen
* This code installs a lightpendriver as an
* InputEvent-Handler.
* Left Mousebutton on Pin 3
* Right Mousebutton on Pin 4
*
* For SAS/C compile with -v
* (no stack checking)
*
* (c) Copyright by Andreas Klingler 1988,1991
*
* This program is freely distributable but is NOT public domain.
* It MAY NOT be included in any commercial package, or sold for
* ANY amount, without written permission from the author.
* However if may be included on any freely distributable package,
* including packages for which a nominal copying fee of no more than
* $5 is charged, as long as this copyright notice keeps intact.
* This software is distributed as-is, without any warranty.
*
* created 31.10.88 akk
* cleanup 27.01.91 akk
*************************************************/
#include <exec/types.h>
#include "intuition/intuition.h"
#include <exec/ports.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <devices/input.h>
#include <exec/devices.h>
#include <devices/inputevent.h>
#include "stdio.h"
#include "stdlib.h"
#include "graphics/gfxbase.h"
#include "graphics/view.h"
#include "proto/dos.h"
#include "proto/exec.h"
#include "proto/intuition.h"
#include "proto/graphics.h"
#include "hardware/custom.h"
/***************** CONSTANTS ********************/
#define LP_ENABLE 0x08
#define XCOMPENSATE 42 /* This is to compensate some timing problems.
You might need to change this. Uh! Again the
answer is 42! What was the question!? */
#define BANNER "\x9B\x30;33mLightpenhandler Version 1.1\x9B\x30m (c) by Andreas Klingler 1988,1991\n"
#define ACTIVATED " Handler installed\n"
#define TERMINATING " Handler removed\n"
#define PORTNAME "lightpen_AKK.port"
/****************** GLOBAL VARIABLES ************/
extern struct Custom __far custom;
struct MsgPort *inputDevPort;
struct IOStdReq *inputRequestBlock;
struct Interrupt handlerStuff;
struct OURMSG {
struct Message msgpart;
short dummy;
} msg;
struct LpInfo { short *ViewX, *ViewY; } handlerdata;
/* Prototypes for functions defined in lp.c */
struct InputEvent * __regargs __saveds myhandler(struct InputEvent *,
struct LpInfo *);
void main(void);
void chkabort(void);
/* Declarations for CBACK */
extern BPTR _Backstdout; /* standard output when run in background */
long _BackGroundIO = 1; /* Flag to tell it we want to do I/O */
long _stack = 4000; /* Amount of stack space our task needs */
char *_procname = "Lightpenhandler"; /* The name of the task to create */
long _priority = 20; /* The priority to run us at */
/******************* Here goes the Handler ****************/
struct InputEvent *
__regargs __saveds myhandler(ev, mydata)
struct InputEvent *ev; /* and a pointer to a list of events */
struct LpInfo *mydata; /* system will pass me a pointer to my
own data space. */
{
static struct InputEvent lpev;
struct InputEvent *retwert;
BOOL lpen_invalid = FALSE,button_pressed = FALSE;
static BOOL left_down,right_down;
ULONG pos;
static ULONG *lpen = (ULONG *)&custom.vposr;
register short x,y;
pos = *lpen; /* read pen position (we read two
registers here: VPOSR,VHPOSR) */
Forbid();
if ((pos != *lpen) || /* Test, if Lpen has been
triggered since VBLANK */
((pos & 0x1ffff) > 0x12a00)) { retwert=ev; lpen_invalid=TRUE; }
else retwert = &lpev;
/* Translate in HIRES INLACE coordinates (depending of position of
the View). That`s what mouse coordinates are in.
Since we have only 8 bits for the horizonal position it gets
a little bit tricky (there are 640 pixel in one line in hires!) */
x = (short)((pos <<1) & 0x1ff);
if (x < 100) x += 454;
y = ((short) (pos >> 8) &0x1ff) - *(mydata->ViewY);
x -= (*(mydata->ViewX) + XCOMPENSATE);
lpev.ie_NextEvent = ev; /* link lpen ahead of event stream */
lpev.ie_Class = IECLASS_POINTERPOS;
lpev.ie_Code = IECODE_NOBUTTON;
lpev.ie_Qualifier = 0;
lpev.ie_TimeStamp.tv_secs = 0;
lpev.ie_TimeStamp.tv_micro = 0;
lpev.ie_X = x << 1;
lpev.ie_Y = y << 1;
/* Button on lightpen pressed ? */
if (right_down) {
if (!(custom.joy1dat & 1)) { lpev.ie_Code = IECODE_RBUTTON |
IECODE_UP_PREFIX;
right_down = FALSE;
button_pressed = TRUE;
}
}
else if (custom.joy1dat & 1) { lpev.ie_Code = IECODE_RBUTTON;
right_down = TRUE;
button_pressed = TRUE;
}
if (left_down) {
if (!(custom.joy1dat & 0x100)){
lpev.ie_Code = IECODE_LBUTTON |
IECODE_UP_PREFIX;
left_down = FALSE;
button_pressed = TRUE;
}
}
else if (custom.joy1dat & 0x100) {
lpev.ie_Code = IECODE_LBUTTON;
left_down = TRUE;
button_pressed = TRUE;
}
/* Append positiondata only if it is valid */
if (button_pressed && lpen_invalid) {
lpev.ie_Class = IECLASS_RAWMOUSE;
lpev.ie_Qualifier = IEQUALIFIER_RELATIVEMOUSE;
lpev.ie_X = lpev.ie_Y = 0;
retwert = &lpev;
}
Permit();
return (retwert);
}
void main()
{
struct MsgPort *port;
SHORT error;
if (_Backstdout) Write(_Backstdout, BANNER, sizeof(BANNER));
/* now see if we are allready installed */
if (!(port = FindPort(PORTNAME))) {
/* if not, install ourself : */
if ((port = CreatePort(PORTNAME,0)) == NULL) _exit (19);
GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0);
if (!GfxBase) _exit(20);
IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0);
if (!IntuitionBase) _exit(21);
/* Tell the OS about the lightpen and enable the hardware */
GfxBase->system_bplcon0 |= LP_ENABLE;
RemakeDisplay();
/* Determine position of the View. Attention: if someone pokes
around with Preferences while we are running, we can`t handle
this! */
handlerdata.ViewX = (short *)&(GfxBase->ActiView->DxOffset);
handlerdata.ViewY = (short *)&(GfxBase->ActiView->DyOffset);
inputDevPort = CreatePort(0,0); /* for input device */
if(inputDevPort == NULL) _exit(1); /* error during createport */
inputRequestBlock=CreateStdIO(inputDevPort);
if(inputRequestBlock == 0) { DeletePort(inputDevPort); _exit(2); }
/* error during createstdio */
handlerStuff.is_Data = (APTR)&handlerdata;
/* address of its data area */
handlerStuff.is_Code = (void *)myhandler;
/* address of entry point to handler */
handlerStuff.is_Node.ln_Pri = 51;
/* set the priority one step higher than
* Intuition, so that our handler enters
* the chain ahead of Intuition.
*/
error = OpenDevice("input.device",0,(struct IORequest *)inputRequestBlock,0);
if(error) _exit(23);
inputRequestBlock->io_Command = IND_ADDHANDLER;
inputRequestBlock->io_Data = (APTR)&handlerStuff;
DoIO((struct IORequest *)inputRequestBlock); /* Activate the Handler */
/* The Handler is running. Close everything we don`t need
anymore and wait until it is time to uninstall the handler.
All the dirty work is done by the handler */
CloseLibrary((struct Library *)IntuitionBase);
CloseLibrary((struct Library *)GfxBase);
if (_Backstdout) { Write(_Backstdout,ACTIVATED, sizeof(ACTIVATED));
Close(_Backstdout);
}
WaitPort(port); /* Wait until we get message */
GetMsg(port); /* to exit, then remove it */
/* and get out */
inputRequestBlock->io_Command = IND_REMHANDLER;
inputRequestBlock->io_Data = (APTR)&handlerStuff;
DoIO((struct IORequest *)inputRequestBlock);
/* close the input device */
CloseDevice((struct IORequest *)inputRequestBlock);
/* delete the IO request */
DeleteStdIO(inputRequestBlock);
/* free other system stuff */
DeletePort(inputDevPort);
DeletePort(port);
} /* this is the end of the BIG-IF (and of the program */
else /* in this case the handler is already installed, so we
send a message to it to make it deinstall itself */
{
msg.msgpart.mn_Length = sizeof(struct OURMSG);
PutMsg(port,(struct Message *)&msg);
if (_Backstdout) { Write(_Backstdout, TERMINATING, sizeof(TERMINATING));
Close(_Backstdout);
}
}
} /* end of main */
void MemCleanup() {} /* We don`t want this out of lc.lib */
void chkabort() {}